/**
 * 给微信发送请求的task
 *
 * @author bian
 * @createDate 2016.8.27
 */

// library module
var util = require("util");

// set request
var superagentPromisePlugin = require("superagent-promise-plugin");
require("es6-promise").polyfill();
var request = superagentPromisePlugin.patch(require("superagent"));
var charset = require("superagent-charset");
charset(request);

// my module
var cache = require("./cache");

// my config
var config = require("./config.json");

/**
 * Task构造函数
 * @param appId
 * @param appSecret
 * @constructor
 */
var Task = function(appId,appSecret){
    this.appId = appId;
    this.appSecret = appSecret;
};

/**
 * 获取AccessToken
 * @returns access_token
 */
Task.prototype.refreshAccessToken = function * (){
    var queryBody = {
        grant_type : "client_credential",
        appid : this.appId,
        secret : this.appSecret
    };

    var res = yield request.get(config.urls.token).query(queryBody);        // 重新获取access_token
    var data = JSON.parse(res.text);
    var accessToken = data["access_token"];
    if(! accessToken){
        throw new Error(res.text);
    }

    var cacheData = {       // cache的数据
        accessToken : accessToken,
        createTime : new Date().getTime(),
    };
    yield cache.jsetex("access_token",7200,cacheData);
    return accessToken;
};

/**
 * 得到redis数据库中
 */
Task.prototype.getAccessToken = function *() {
    var cacheData = yield cache.jget("access_token");   // 得到cache的数据
    var expireTime = new Date().getTime();      // 得到当前时间
    var accessToken;

    if(util.isNullOrUndefined(cacheData) || (expireTime - cacheData.createTime < 3600)){    // 如果存储数据为空或将过期
        accessToken = yield this.refreshAccessToken();
    }

    return accessToken || cacheData.accessToken;
};

/**
 * 检查返回数据是否显示access_token过期
 * @param res response 对象或者 res.text 对象
 * @returns {*|boolean}
 */
Task.prototype.checkAccessToken = function (res){
    res = res.text || res;
    return res["errcode"] && res["errcode"] === 42001;
};

/**
 * 得到用户列表
 * @returns {*}
 */
Task.prototype.getUserList = function *() {
    var userList;       // 用户列表
    var access_token = yield this.getAccessToken();

    var res = yield request.get(config.urls.user_list).query({access_token:access_token,next_openid:""});   // 获得用户列表
    var data = JSON.parse(res.text);
    if(util.isNullOrUndefined(data.data ) || util.isNullOrUndefined(data.data.openid)){
        throw new Error(res.text);
    }

    userList = data.data.openid;
    return userList;        // 返回用户列表数组
};

/**
 * 得到某一用户的昵称和头像
 * @param openId
 * @returns {{nickName: *, headImgUrl: *}|*}
 */
Task.prototype.getUserInfo = function *(openId){
    var userInfo;   // 用户信息
    var access_token = yield this.getAccessToken();

    var res = yield request.get(config.urls.user_info).query({access_token:access_token,openid:openId,lang:"zh_CN"});
    var data = JSON.parse(res.text);
    if(util.isNullOrUndefined(data.nickname) || util.isNullOrUndefined(data.headimgurl)){
        throw new Error(res.text);
    }

    userInfo = {            // 返回昵称和头像性别和地理位置以及是否订阅
        nickName : data.nickname,
        headImgUrl : data.headimgurl,
        sex : data.sex,
        city : data.city,
        province : data.province,
        country : data.country,
        openId : data.openid,
        subscribe : data.subscribe
    };
    return userInfo;
};

/**
 * 得到所有关注者的信息
 * @returns ARRAY 带有昵称和头像的关注者的信息
 */
Task.prototype.getAllUsersInfo = function *(){
    var user
        ,usersInfo = []
        ,users = yield this.getUserList();

    for(user of users){
        usersInfo.push(
            yield this.getUserInfo(user)
        );
    }

    return usersInfo;
};

/**
 * 得到二维码的ticket，返回二维码的url值
 * @param sceneId   设置的情景的id
 * @param isExpire  是否过期
 */
Task.prototype.getQrCode = function *(sceneId,isExpire){
    var accessToken = yield this.getAccessToken();

    var postData = {
        expire_seconds : isExpire ? 60 * 60 * 24 * 3 : undefined,
        action_name : isExpire ? "QR_SCENE" : "QR_LIMIT_SCENE",
        action_info : {
            scene : {
                scene_id : sceneId
            }
        }
    };
    var res = yield request
        .post(config.urls.qr_code)
        .query({access_token : accessToken})
        .send(postData);
    var data = JSON.parse(res.text);
    if(util.isNullOrUndefined(data.ticket)){
        throw new Error(res.text);
    }

    var ticket = data.ticket;
    return `${config.urls.qr_code_img}?ticket=${ticket}`;
};

module.exports = Task;